/*customer.c*/
#include "cineplex.h"

void Customer_Scheduler(int index)
{
	agentsStarted = agentsStarted + 1;
	Wait(initCond, initLock);
	customers[index].runScheduler = runSchedulers;
	do {
		/*LEADER*/
		if(customers[index].state  == JOINTIXLINE)
		{
			Customer_JoinTixLine(index);
		}else if(customers[index].state == WAITTIXLINE)
		{
			Customer_WaitTixLine(index);
		}else if(customers[index].state == CHECKNEWTIXLINE)
		{
			Customer_CheckNewTixLine(index);
		}else if(customers[index].state == RECTIXCLERK)
		{
			Customer_RecTixClerk(index);
		}else if(customers[index].state == TIXORDERPLACED)
		{
			Customer_TixOrderPlaced(index);
		}else if(customers[index].state == TIXPAYSENT)
		{
			Customer_TixPaySent(index);
		}else if(customers[index].state == ASKSUBSFOOD)
		{
			Customer_AskSubsFood(index);
		}else if(customers[index].state == WAITSUBFOOD)
		{
			Customer_WaitSubFood(index);
		}else if(customers[index].state == JOINFOODLINE)
		{
			Customer_JoinFoodLine(index);
		}else if(customers[index].state == WAITFOODLINE)
		{
			Customer_WaitFoodLine(index);
		}else if(customers[index].state == CHECKNEWFOODLINE)
		{
			Customer_CheckNewFoodLine(index);
		}else if(customers[index].state == RECFOODCLERK)
		{
			Customer_RecFoodClerk(index);
		}else if(customers[index].state == POPCORNORDERPLACED)
		{
			Customer_PopcornOrderPlaced(index);
		}else if(customers[index].state == DRINKORDERPLACED)
		{
			Customer_DrinkOrderPlaced(index);
		}else if(customers[index].state == FOODPAYSENT)
		{
			Customer_FoodPaySent(index);
		}else if(customers[index].state == JOINENTRYLINE)
		{
			Customer_JoinEntryLine(index);
		}else if(customers[index].state == WAITENTRYLINE)
		{
			Customer_WaitEntryLine(index);
		}else if(customers[index].state == CHECKNEWENTRYLINE)
		{
			Customer_CheckNewEntryLine(index);
		}else if(customers[index].state == RECTIXTAKER)
		{
			Customer_RecTixTaker(index);
		}else if(customers[index].state == GAVETIX)
		{
			Customer_GaveTix(index);
		}else if(customers[index].state == TELLSUBSGOIN)
		{
			Customer_TellSubsGoIn(index);
		}else if(customers[index].state == LEADGOIN)
		{
			Customer_LeadGoIn(index);
		}else if(customers[index].state == WATCHINGMOVIE)
		{
			Customer_WatchingMovie(index);
		}else if(customers[index].state == LEADREGROUP)
		{
			Customer_LeadRegroup(index);
		}else if(customers[index].state == ASKUSEBR)
		{
			Customer_AskUseBR(index);
		}else if(customers[index].state == FINDOUTBR)
		{
			Customer_FindOutBR(index);
		}else if(customers[index].state == WAITBR)
		{
			Customer_WaitBR(index);
		}else if(customers[index].state == LEAVECINEPLEX)
		{
			Customer_LeaveCineplex(index);
		}else if(customers[index].state == GOTOLOBBY)
		{
			Customer_GoToLobby(index);
		}else if(customers[index].state == INLOBBY)
		{
			Customer_InLobby(index);
		}else if(customers[index].state == RECSIZEREQUEST)
		{
			Customer_RecSizeRequest(index);
		}
		
		/*SUBS*/
		else if(customers[index].state == SNEWSUB)
		{
			Customer_sNewSub(index);
		}else if(customers[index].state == SSENDFOODORDER)
		{
			Customer_sSendFoodOrder(index);
		}else if(customers[index].state == SFOODORDERSENT)
		{
			Customer_sFoodOrderSent(index);
		}else if(customers[index].state == SRECGOIN)
		{
			Customer_sRecGoIn(index);
		}else if(customers[index].state == SWAITFORSEAT)
		{
			Customer_sWaitForSeat(index);
		}else if(customers[index].state == SWATCHINGMOVIE)
		{
			Customer_sWatchingMovie(index);
		}else if(customers[index].state == SREGROUP)
		{
			Customer_sRegroup(index);
		}else if(customers[index].state == SLEAVETHEATER)
		{
			Customer_sLeaveTheater(index);
		}else if(customers[index].state == SASKEDBR)
		{
			Customer_sAskedBR(index);
		}else if(customers[index].state == SUSEBR)
		{
			Customer_sUseBR(index);
		}else if(customers[index].state == SWAITBR)
		{
			Customer_sWaitBR(index);
		}else if(customers[index].state == SLEAVECINEPLEX)
		{
			Customer_sLeaveCineplex(index);
		}
		
		/*terminate thread*/
		else if(customers[index].state == COMPLETED)
		{
			ConsoleAcquire();
			Write("Customer #", 10, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write( outBuff, outputLen, ConsoleOutput );
			Write(" completed\n", 11, ConsoleOutput);
			ConsoleRelease();
			customersRunning = customersRunning - 1;
			customers[index].runScheduler = 0;
			Exit(0);
		}
	} while(customers[index].runScheduler);
}

struct Message Customer_GetMessage(int index, int name)
{
	/*this will be the null output*/
	customers[index].tempMsg.name = NullMsg;
	customers[index].tempMsg.sender = NullMsg;
	
	Acquire(loopLock);
	for(i = 0; i < customers[index].numMsgs; i++)
	{
		if(customers[index].msgList[i].name == name)
		{
			customers[index].tempMsg.name = name;
			customers[index].tempMsg.sender = customers[index].msgList[i].sender;
			customers[index].numMsgs = customers[index].numMsgs - 1;
			break;
		}
	}
	for(k = i; k < MAX_GROUP_SIZE; k++)
	{
		/*movin on up*/
		customers[index].msgList[k].name = customers[index].msgList[k+1].name;
		customers[index].msgList[k].sender = customers[index].msgList[k+1].sender;
	}
	customers[index].msgList[MAX_GROUP_SIZE].name = NullMsg;
	customers[index].msgList[MAX_GROUP_SIZE].sender = NullMsg;
	Release(loopLock);
		
	return customers[index].tempMsg;
}

/*LEADER ACTIONS*/
void Customer_JoinTixLine(int index)
{
	Acquire(tixLinesLock);
	t1 = -1; /*shortest*/
	t2 = NUM_CUSTOMERS; /*shortLen*/
	Acquire(loopLock);
	Acquire(tempLock);
	for(i = 0; i < NUM_TIX_CLERKS; i++)
	{
		t3 = Line_getSize(T_TICKETCLERK, i); /*currLen*/
		if(t3 == -1) continue;
		if(t3 < t2)
		{
			t2 = t3;
			t1 = i;
		}
	}
	Release(loopLock);
	
	customers[index].currentLine = t1;
	Release(tempLock);
	
	Line_Enqueue(T_TICKETCLERK, customers[index].currentLine, index);
	/*printf("Customer %s in Group %d is getting in TicketClerk line %d\n", myName, groupNumber, shortest);*/
	ConsoleAcquire();
	Write("Customer ", 9, ConsoleOutput);
	outputLen = Itoa(index, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write(" in Group ", 10, ConsoleOutput);
	outputLen = Itoa(customers[index].groupNumber, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write(" is getting in TicketClerk line ", 32, ConsoleOutput);
	outputLen = Itoa(customers[index].currentLine, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write("\n", 1, ConsoleOutput);
	ConsoleRelease();
	customers[index].state = WAITTIXLINE;
	
	Release(tixLinesLock);
}

void Customer_WaitTixLine(int index)
{
	/*if this line closed, join a new one*/
	if(!tixLines[customers[index].currentLine].isOpen)
	{
		customers[index].state = JOINTIXLINE;
	}else{
		Acquire(customers[index].msgLock);
		Customer_GetMessage(index, ComeBuyTix);
		if(customers[index].tempMsg.sender > -1)
		{
			customers[index].replyTo = customers[index].tempMsg.sender;
			customers[index].state = RECTIXCLERK;
		}
		else customers[index].state = CHECKNEWTIXLINE;
		Release(customers[index].msgLock);
	}
	Yield();
}

void Customer_CheckNewTixLine(int index)
{
 	Acquire(tixLinesLock);
	Acquire(loopLock);
	Acquire(tempLock);
	/*int shortest*/t1 = -1;
	/*int shortLen*/t2 = Line_getSize(T_TICKETCLERK, customers[index].currentLine);
	for(i = 0; i < NUM_TIX_CLERKS; i++)
	{
		/*int currLen*/t3 = Line_getSize(T_TICKETCLERK, i);
		if(t3 == -1) continue;
		if(t1 == -1) /*haven't found line shorter than own */
		{
			if(t3 < t2 - 1) /*at least two shorter, or position wouldn't improve*/
			{
				t2 = t3;
				t1 = i;
			}
		}else{
			if(t3 < t2) /*already sufficiently shorter than own line*/
			{
				t3 = t2;
				t1 = i;
			}
		}
	}
	
	if(t1 != -1)
	{
		Line_Dequeue(T_TICKETCLERK, customers[index].currentLine, index);
		customers[index].currentLine = t1;
		/*printf("Customer %s in Group %d is moving to TicketClerk line %d\n", myName, groupNumber, shortest);*/
		ConsoleAcquire();
		Write("Customer ", 9, ConsoleOutput);
		outputLen = Itoa(index, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" in Group ", 10, ConsoleOutput);
		outputLen = Itoa(customers[index].groupNumber, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" is moving to TicketClerk line ", 31, ConsoleOutput);
		outputLen = Itoa(customers[index].currentLine, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write("\n", 1, ConsoleOutput);
		ConsoleRelease();
		Line_Enqueue(T_TICKETCLERK, customers[index].currentLine, index);
	}
	
	customers[index].state = WAITTIXLINE;
	
	Release(loopLock);
	Release(tempLock);
	Release(tixLinesLock);
}

void Customer_RecTixClerk(int index)
{
	/*printf("Customer %s in Group %d is walking up to %s to buy %d tickets\n", myName, groupNumber, ((TicketClerk*)replyTo)->myName, numSubs+1);*/
	ConsoleAcquire();
	Write("Customer ", 9, ConsoleOutput);
	outputLen = Itoa(index, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write(" in Group ", 10, ConsoleOutput);
	outputLen = Itoa(customers[index].groupNumber, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write(" is walking up to TC-", 21, ConsoleOutput);
	outputLen = Itoa(customers[index].replyTo, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write(" to buy ", 8, ConsoleOutput);
	outputLen = Itoa(groupSizes[groupNums[index]], outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write(" tickets\n", 9, ConsoleOutput);
	ConsoleRelease();
	/*((TicketClerk*)replyTo)->SendMessage("OrderTix", 2, this, &msgInt);///&tix);*/
	Line_Dequeue(T_TICKETCLERK, customers[index].currentLine, index);
	SendMessage(T_TICKETCLERK, customers[index].replyTo, OrderTix, index);
	customers[index].state = TIXORDERPLACED;
}

void Customer_TixOrderPlaced(int index)
{
	Acquire(customers[index].msgLock);
	/*IterList* clerkMsg = msgList->Find("PayMeForTix");*/
	Customer_GetMessage(index, PayMeForTix);
	if(customers[index].tempMsg.sender > NullMsg)
	{
		customers[index].money -= groupSizes[groupNums[index]]*tixClerks[customers[index].replyTo].TICKET_PRICE; /*that value is static, don't need a lock*/
		/*printf("Customer %s in Group %d is paying %s $%f for tickets\n", myName, groupNumber, ((TicketClerk*)replyTo)->myName, msgFloat);*/
		SendMessage(T_TICKETCLERK, customers[index].replyTo, HereIsTixMoney, index);
		customers[index].state = TIXPAYSENT;
		Release(customers[index].msgLock);
	}else{
		Wait(customers[index].sleepCon, customers[index].msgLock);
	}
}

void Customer_TixPaySent(int index)
{
	Acquire(customers[index].msgLock);
	/*IterList* clerkMsg = msgList->Find("HereAreTickets");*/
	Customer_GetMessage(index, HereAreTickets);
	if(customers[index].tempMsg.sender > NullMsg)
	{
		Acquire(poolLock);
		customers[index].tickets = tixPassedOut;
		tixPassedOut = tixPassedOut + groupSizes[customers[index].groupNumber];
		Release(poolLock);
		customers[index].msgsToSend = customers[index].numSubs;
		customers[index].numPopcorn = ((getRandPercent() < 75) ? 1 : 0); /*decide own popcorn*/
		customers[index].numSoda = ((getRandPercent() < 75) ? 1 : 0); /*decide own soda*/
		/*printf("Customer %s in Group %d is leaving %s\n", myName, groupNumber, ((TicketClerk*)replyTo)->myName);*/
		ConsoleAcquire();
		Write("Customer ", 9, ConsoleOutput);
		outputLen = Itoa(index, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" in Group ", 10, ConsoleOutput);
		outputLen = Itoa(customers[index].groupNumber, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" is paying TC-", 14, ConsoleOutput);
		outputLen = Itoa(customers[index].replyTo, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" $", 2, ConsoleOutput);
		outputLen = Itoa(groupSizes[groupNums[index]]*tixClerks[customers[index].replyTo].TICKET_PRICE, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" for tickets\n", 13, ConsoleOutput);
		ConsoleRelease();

		customers[index].state = ASKSUBSFOOD;
		Release(customers[index].msgLock);
	}else{
		Wait(customers[index].sleepCon, customers[index].msgLock);
	}
}

void Customer_AskSubsFood(int index)
{
	if(customers[index].msgsToSend == 0)
	{
		customers[index].repliesWaiting = customers[index].numSubs;
		customers[index].state = WAITSUBFOOD;
	}else{
		/*ConsoleAcquire();
			Write("Customer ", 9, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" is asking sub for food order.\n", 31, ConsoleOutput);
		ConsoleRelease();*/
		
		customers[index].replyTo = groups[customers[index].groupNumber][customers[index].msgsToSend-1];
		/*((Customer*)replyTo)->SendMessage("WouldYouLikeFood",1,this);*/
		SendMessage(T_CUSTOMER, customers[index].replyTo, WouldYouLikeFood, index);
		customers[index].msgsToSend = customers[index].msgsToSend - 1;
	}
}

void Customer_WaitSubFood(int index)
{
		/*ConsoleAcquire();
				Write("Customer ", 9, ConsoleOutput);
				outputLen = Itoa(index, outBuff);
				Write(outBuff , outputLen, ConsoleOutput);
				Write(" WSF\n", 5, ConsoleOutput);
		ConsoleRelease();*/
	if(customers[index].repliesWaiting == 0)
	{
		/*ConsoleAcquire();
				Write("Customer ", 9, ConsoleOutput);
				outputLen = Itoa(index, outBuff);
				Write(outBuff , outputLen, ConsoleOutput);
				Write(" has received all orders\n", 25, ConsoleOutput);
		ConsoleRelease();*/
		if(!customers[index].numSoda && !customers[index].numPopcorn) customers[index].state = JOINENTRYLINE;
		else customers[index].state = JOINFOODLINE;
	}else{
		Acquire(customers[index].msgLock);
		/*IterList* foodMsg = msgList->Find("IWouldLike");*/
		Customer_GetMessage(index, IWouldLike);
		if(customers[index].tempMsg.sender > NullMsg)
		{
			/*ConsoleAcquire();
				Write("Customer ", 9, ConsoleOutput);
				outputLen = Itoa(index, outBuff);
				Write(outBuff , outputLen, ConsoleOutput);
				Write(" is receiving food order - ", 27, ConsoleOutput);
				outputLen = Itoa(customers[index].repliesWaiting-1, outBuff);
				Write(outBuff , outputLen, ConsoleOutput);
				Write(" more required.\n", 16, ConsoleOutput);				
			ConsoleRelease();*/
			customers[index].numPopcorn = customers[index].numPopcorn + customers[customers[index].tempMsg.sender].numPopcorn;
			customers[index].numSoda = customers[index].numSoda + customers[customers[index].tempMsg.sender].numSoda;
			Release(customers[index].msgLock);
			customers[index].repliesWaiting--;
		}else{
			Wait(customers[index].sleepCon, customers[index].msgLock);
		}
	}
}

void Customer_JoinFoodLine(int index)
{
	Acquire(foodLinesLock);
	t1 = -1; /*shortest*/
	t2 = NUM_CUSTOMERS; /*shortLen*/
	Acquire(loopLock);
	Acquire(tempLock);
	for(i = 0; i < NUM_FOOD_CLERKS; i++)
	{
		t3 = Line_getSize(T_FOODCLERK, i); /*currLen*/
		if(t3 == -1) continue;
		if(t3 < t2)
		{
			t2 = t3;
			t1 = i;
		}
	}
	Release(loopLock);
	
	customers[index].currentLine = t1;
	Release(tempLock);
	
	Line_Enqueue(T_FOODCLERK, customers[index].currentLine, index);
	/*printf("Customer %s in Group %d is getting in FoodClerk line %d\n", myName, groupNumber, shortest);*/
	ConsoleAcquire();
	Write("Customer ", 9, ConsoleOutput);
	outputLen = Itoa(index, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write(" in Group ", 10, ConsoleOutput);
	outputLen = Itoa(customers[index].groupNumber, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write(" is getting in FoodClerk line ", 30, ConsoleOutput);
	outputLen = Itoa(customers[index].currentLine, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write("\n", 1, ConsoleOutput);
	ConsoleRelease();
	customers[index].state = WAITTIXLINE;
	customers[index].state = WAITFOODLINE;
	
	Release(foodLinesLock);
}

void Customer_WaitFoodLine(int index)
{
	/*if this line closed, join a new one*/
	if(!foodLines[customers[index].currentLine].isOpen)
	{
		customers[index].state = JOINFOODLINE;
	}else{
		Acquire(customers[index].msgLock);
		Customer_GetMessage(index, ComeBuyFood);
		if(customers[index].tempMsg.sender > -1)
		{
			customers[index].replyTo = customers[index].tempMsg.sender;
			customers[index].state = RECFOODCLERK;
		}
		else customers[index].state = CHECKNEWFOODLINE;
		Release(customers[index].msgLock);
	}
	Yield();
}

void Customer_CheckNewFoodLine(int index)
{
 	Acquire(foodLinesLock);
	Acquire(loopLock);
	Acquire(tempLock);
	/*int shortest*/t1 = -1;
	/*int shortLen*/t2 = Line_getSize(T_FOODCLERK, customers[index].currentLine);
	for(i = 0; i < NUM_FOOD_CLERKS; i++)
	{
		/*int currLen*/t3 = Line_getSize(T_FOODCLERK, i);
		if(t3 == -1) continue;
		if(t1 == -1) /*haven't found line shorter than own */
		{
			if(t3 < t2 - 1) /*at least two shorter, or position wouldn't improve*/
			{
				t2 = t3;
				t1 = i;
			}
		}else{
			if(t3 < t2) /*already sufficiently shorter than own line*/
			{
				t3 = t2;
				t1 = i;
			}
		}
	}
	
	if(t1 != -1)
	{
		Line_Dequeue(T_FOODCLERK, customers[index].currentLine, index);
		customers[index].currentLine = t1;
		/*printf("Customer %s in Group %d is moving to TicketClerk line %d\n", myName, groupNumber, shortest);*/
		Line_Enqueue(T_FOODCLERK, customers[index].currentLine, index);
	}
	
	customers[index].state = WAITFOODLINE;
	
	Release(loopLock);
	Release(tempLock);
	Release(foodLinesLock);
}

void Customer_RecFoodClerk(int index)
{
	/*printf("Customer %s in Group %d is walking up to %s to buy %d popcorns and %d sodas\n", myName, groupNumber, ((FoodClerk*)replyTo)->myName, numPopcorn, numSoda);*/
	/*((FoodClerk*)replyTo)->SendMessage("WantPopcorn", 2, this, &numPopcorn);*/
	Line_Dequeue(T_FOODCLERK, customers[index].currentLine, index);
	SendMessage(T_FOODCLERK, customers[index].replyTo, WantPopcorn, index);
	customers[index].state = POPCORNORDERPLACED;
}

void Customer_PopcornOrderPlaced(int index)
{
	Acquire(customers[index].msgLock);
	/*IterList* clerkMsg = msgList->Find("AnythingElse");*/
	Customer_GetMessage(index, AnythingElse);
	if(customers[index].tempMsg.sender > -1)
	{
		/*((TicketClerk*)replyTo)->SendMessage("WantSoda", 2, this, &numSoda);*/
		SendMessage(T_FOODCLERK, customers[index].replyTo, WantSoda, index);
		customers[index].state = DRINKORDERPLACED;
		Release(customers[index].msgLock);
	}else{
		Wait(customers[index].sleepCon, customers[index].msgLock);
	}
}

void Customer_DrinkOrderPlaced(int index)
{
	Acquire(customers[index].msgLock);
	/*IterList* clerkMsg = msgList->Find("PayMeForFood");*/
	Customer_GetMessage(index, PayMeForFood);
	if(customers[index].tempMsg.sender > -1)
	{
		customers[index].money -= (foodClerks[customers[index].replyTo].POPCORN_PRICE*customers[index].numPopcorn +  foodClerks[customers[index].replyTo].SODA_PRICE*customers[index].numSoda ); /*prices are static*/
		/*printf("Customer %s in Group %d is paying %s $%f for food\n", myName, groupNumber, ((FoodClerk*)replyTo)->myName, cost);*/
		ConsoleAcquire();
			Write("Customer ", 9, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" in Group ", 10, ConsoleOutput);
			outputLen = Itoa(customers[index].groupNumber, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" is paying FC ", 14, ConsoleOutput);
			outputLen = Itoa(customers[index].replyTo, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" $", 2, ConsoleOutput);
			outputLen = Itoa((foodClerks[customers[index].replyTo].POPCORN_PRICE*customers[index].numPopcorn +  foodClerks[customers[index].replyTo].SODA_PRICE*customers[index].numSoda ), outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" for food\n", 10, ConsoleOutput);
		ConsoleRelease();
		/*((FoodClerk*)replyTo)->SendMessage("HereIsFoodMoney", 2,this, &cost);*/
		SendMessage(T_FOODCLERK, customers[index].replyTo, HereIsFoodMoney, index);
		customers[index].state = FOODPAYSENT;
		Release(customers[index].msgLock);
	}else{
		Wait(customers[index].sleepCon, customers[index].msgLock);
	}
}

void Customer_FoodPaySent(int index)
{
	Acquire(customers[index].msgLock);
	/*IterList* clerkMsg = msgList->Find("HereIsYourFood");*/
	Customer_GetMessage(index, HereIsYourFood);
	if(customers[index].tempMsg.sender > -1)
	{
		Acquire(poolLock);
		customers[index].popcorns = popcornSold;
		customers[index].sodas = sodaSold;
		popcornSold = popcornSold + customers[index].numPopcorn;
		sodaSold = sodaSold + customers[index].numSoda;
		Release(poolLock);
		/*printf("Customer %s in Group %d is leaving %s\n", myName, groupNumber, ((FoodClerk*)replyTo)->myName);*/
		customers[index].state = JOINENTRYLINE;
		Release(customers[index].msgLock);
	}else{
		Wait(customers[index].sleepCon, customers[index].msgLock);
	}
}

void Customer_JoinEntryLine(int index)
{
	Acquire(entryLinesLock);
	t1 = -1; /*shortest*/
	t2 = NUM_CUSTOMERS; /*shortLen*/
	Acquire(loopLock);
	Acquire(tempLock);
	for(i = 0; i < NUM_TIX_TAKERS; i++)
	{
		t3 = Line_getSize(T_TICKETTAKER, i); /*currLen*/
		if(t3 == -1) continue;
		if(t3 < t2)
		{
			t2 = t3;
			t1 = i;
		}
	}
	Release(loopLock);
	
	customers[index].currentLine = t1;
	Release(tempLock);
	
	Line_Enqueue(T_TICKETTAKER, customers[index].currentLine, index);
	/*printf("Customer %s in Group %d is getting in TicketClerk line %d\n", myName, groupNumber, shortest);*/
	ConsoleAcquire();
		Write("Customer ", 9, ConsoleOutput);
		outputLen = Itoa(index, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" in Group ", 10, ConsoleOutput);
		outputLen = Itoa(customers[index].groupNumber, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" is getting in TicketTaker line ", 32, ConsoleOutput);
		outputLen = Itoa(customers[index].currentLine, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write("\n", 1, ConsoleOutput);
	ConsoleRelease();
	customers[index].state = WAITENTRYLINE;
	
	Release(entryLinesLock);
}

void Customer_WaitEntryLine(int index)
{
	/*if this line closed, join a new one*/
	if(!entryLines[customers[index].currentLine].isOpen)
	{
		customers[index].state = JOINENTRYLINE;
	}else{
		Acquire(customers[index].msgLock);
		Customer_GetMessage(index, GoToTicketTaker);
		if(customers[index].tempMsg.sender > -1)
		{
			customers[index].replyTo = customers[index].tempMsg.sender;
			customers[index].state = RECTIXTAKER;
		}
		else customers[index].state = CHECKNEWENTRYLINE;
		Release(customers[index].msgLock);
	}
	Yield();
}

void Customer_CheckNewEntryLine(int index)
{
 	Acquire(entryLinesLock);
	Acquire(loopLock);
	Acquire(tempLock);
	/*int shortest*/t1 = -1;
	/*int shortLen*/t2 = Line_getSize(T_TICKETTAKER, customers[index].currentLine);
	for(i = 0; i < NUM_TIX_TAKERS; i++)
	{
		/*int currLen*/t3 = Line_getSize(T_TICKETTAKER, i);
		if(t3 == -1) continue;
		if(t1 == -1) /*haven't found line shorter than own */
		{
			if(t3 < t2 - 1) /*at least two shorter, or position wouldn't improve*/
			{
				t2 = t3;
				t1 = i;
			}
		}else{
			if(t3 < t2) /*already sufficiently shorter than own line*/
			{
				t3 = t2;
				t1 = i;
			}
		}
	}
	
	if(t1 != -1)
	{
		Line_Dequeue(T_TICKETTAKER, customers[index].currentLine, index);
		customers[index].currentLine = t1;
		/*printf("Customer %s in Group %d is moving to TicketClerk line %d\n", myName, groupNumber, shortest);*/
		ConsoleAcquire();
			Write("Customer ", 9, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" in Group ", 10, ConsoleOutput);
			outputLen = Itoa(customers[index].groupNumber, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" is moving to TicketTaker line ", 31, ConsoleOutput);
			outputLen = Itoa(customers[index].currentLine, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write("\n", 1, ConsoleOutput);
		ConsoleRelease();
		Line_Enqueue(T_TICKETTAKER, customers[index].currentLine, index);
	}
	
	customers[index].state = WAITENTRYLINE;
	
	Release(loopLock);
	Release(tempLock);
	Release(entryLinesLock);
}

void Customer_RecTixTaker(int index)
{
	/*printf("Customer %s in Group %d is walking up to %s to give %d tickets\n", myName, groupNumber, ((TicketTaker*)replyTo)->myName, numSubs+1);*/
	ConsoleAcquire();
		Write("Customer ", 9, ConsoleOutput);
		outputLen = Itoa(index, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" in Group ", 10, ConsoleOutput);
		outputLen = Itoa(customers[index].groupNumber, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" is walking up to TT-", 21, ConsoleOutput);
		outputLen = Itoa(customers[index].replyTo, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" to give ", 9, ConsoleOutput);
		outputLen = Itoa(groupSizes[groupNums[index]], outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" tickets\n", 9, ConsoleOutput);
	ConsoleRelease();
	/*msgInt = numSubs+1;*/
	/*((TicketTaker*)replyTo)->SendMessage("HereAreTix", 3, this, tickets, &msgInt);*/
	Line_Dequeue(T_TICKETTAKER, customers[index].currentLine, index);
	SendMessage(T_TICKETTAKER, customers[index].replyTo, HereAreTix, index);
	customers[index].state = GAVETIX;
}

void Customer_GaveTix(int index)
{
	Acquire(customers[index].msgLock);
	/*IterList* yesMsg = msgList->Find("GoOnIn");*/
	Customer_GetMessage(index, GoOnIn);
	if(customers[index].tempMsg.sender > -1)
	{
		ConsoleAcquire();
			Write("Customer ", 9, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write(outBuff, outputLen, ConsoleOutput);
			Write(" received go in\n", 16, ConsoleOutput);
		ConsoleRelease();
		customers[index].msgsToSend = customers[index].numSubs;
		/*printf("Customer %s in Group %d is leaving %s to enter theater\n", myName, groupNumber, ((TicketTaker*)replyTo)->myName);*/
		customers[index].state = TELLSUBSGOIN;
		Release(customers[index].msgLock);
	}else{
		/*IterList* noMsg = msgList->Find("GoToLobby");*/
		Customer_GetMessage(index, GoToLobby);
		if(customers[index].tempMsg.sender > -1)
		{
			/*printf("Customer %s in Group %d is leaving %s to wait in the lobby\n", myName, groupNumber, ((TicketClerk*)replyTo)->myName);*/
			ConsoleAcquire();
				Write("Customer ", 9, ConsoleOutput);
				outputLen = Itoa(index, outBuff);
				Write(outBuff, outputLen, ConsoleOutput);
				Write(" received go to lobby\n", 22, ConsoleOutput);
			ConsoleRelease();
			customers[index].replyTo = customers[index].tempMsg.sender;
			customers[index].state = GOTOLOBBY;
			Release(customers[index].msgLock);
		}else{
			Wait(customers[index].sleepCon, customers[index].msgLock);
		}
	}
}

void Customer_TellSubsGoIn(int index)
{
	if(customers[index].msgsToSend == 0)
	{
		customers[index].state = LEADGOIN;
		/*((TicketTaker*)replyTo)->SendMessage("ImGoingIn",0);*/
		SendMessage(T_TICKETTAKER, customers[index].replyTo, ImGoingIn, index);
		ConsoleAcquire();
			Write("Customer ", 9, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write(outBuff, outputLen, ConsoleOutput);
			Write(" is going in\n", 13, ConsoleOutput);
		ConsoleAcquire();
	}else
	{
		/*((Customer*)subs->Get(msgsToSend-1))->SendMessage("GoOnIn",1,replyTo);*/
		ConsoleAcquire();
			Write("Customer ", 9, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write(outBuff, outputLen, ConsoleOutput);
			Write(" sending in sub\n", 16, ConsoleOutput);
		ConsoleAcquire();
		SendMessage(T_CUSTOMER, customers[index].replyTo, GoOnIn, index);
		customers[index].msgsToSend = customers[index].msgsToSend - 1;
	}
}

void Customer_LeadGoIn(int index)
{
	Acquire(seatingLock);
	
/*	///////////////////////////  */
/*	//SEAT CHOOSING ALGORITHM//  */
/*	///////////////////////////  */

	Acquire(loopLock);
	for(i=0;i<NUM_ROWS;i++)
	{
		OpenSeatsInRow[i]=0;
	}
	for(i=0;i<NUM_ROWS;i++)
	{
		for(j=0;j<NUM_COLS;j++)
		{
			if(seating[i*NUM_COLS+j] == -1)
			{
				OpenSeatsInRow[i]++;
			}
		}
	}
	
	/*Now I know how many open seats there are in each row*/
	/*If there is a row with enough seats to fit the entire group, seat the group in that row*/
	for(i=0;i<NUM_ROWS;i++)
	{
		if(OpenSeatsInRow[i] >= customers[i].numSubs+1)
		{
			startingSeat=i*NUM_COLS+(NUM_COLS-OpenSeatsInRow[i]);
			seating[startingSeat]=index;
	
			customers[i].myRow=i;
			customers[i].myCol=NUM_COLS-OpenSeatsInRow[i];
			for(j=1; j < customers[i].numSubs+1; j++)
			{
				r = (startingSeat+j) / NUM_COLS;
				c = (startingSeat+j) % NUM_COLS;
				/*printf("%s is putting %s in seat %d-%d\n",myName,((Customer *)subs->Get(j -1))->myName,*r,*c);*/
				/*((Customer *)subs->Get(j -1))->SendMessage("YouAreInSeat",3,this,r,c);*/
				k = groups[customers[i].groupNumber][j-1];
				seatAssign[k].row = r;
				seatAssign[k].col = c;
				SendMessage(T_CUSTOMER, groups[customers[i].groupNumber][j-1], YouAreInSeat, index);
				/*cinema->theater->seating[startingSeat+j] = ((Customer *)subs->Get(j -1));*/
				seating[startingSeat+j] = groups[customers[i].groupNumber][j-1];
			}
			_seated=1;
			break;
		}
	}
	/*If there is not space in a single row, then check if there is space in two adjacent rows*/
	if(!_seated)
	{
		for(i=0;i<NUM_ROWS-1;i++)
		{
			startingSeat = 0;
			numTakenInRow=0;
			if(OpenSeatsInRow[i]+OpenSeatsInRow[i+1] >= customers[i].numSubs+1)
			{
				startingSeat=i*NUM_COLS+(NUM_COLS-OpenSeatsInRow[i]);
				seating[startingSeat]=index;
				customers[i].myRow=i;
				customers[i].myCol=NUM_COLS-OpenSeatsInRow[i];
				for(j=1;OpenSeatsInRow[i]-j>0;j++)
				{
					r = (startingSeat+j) / NUM_COLS;
					c = (startingSeat+j) % NUM_COLS;
					/*((Customer *)subs->Get(j -1))->SendMessage("YouAreInSeat",3,this,r,c);*/
					seatAssign[groups[customers[i].groupNumber][j-1]].row = r;
					seatAssign[groups[customers[i].groupNumber][j-1]].col = c;
					SendMessage(T_CUSTOMER, groups[customers[i].groupNumber][j-1], YouAreInSeat, index);
					/*printf("%s is putting %s in seat %d-%d\n",myName,((Customer *)subs->Get(j -1))->myName,*r,*c);*/
					seating[startingSeat+j] = groups[customers[i].groupNumber][j-1];
				}
				i++;
				/*Sat as many as possible in the first row, and now will put people in the next row*/
				startingSeat=(i)*NUM_COLS+(NUM_COLS-OpenSeatsInRow[i]);
				
				for(j=j;j<customers[i].numSubs+1;j++)
				{
					r = (startingSeat+numTakenInRow) / NUM_COLS;
					c = (startingSeat+numTakenInRow) % NUM_COLS;
					/*((Customer *)subs->Get(j -1))->SendMessage("YouAreInSeat",3,this,r,c);*/
					seatAssign[groups[customers[i].groupNumber][j-1]].row = r;
					seatAssign[groups[customers[i].groupNumber][j-1]].col = c;
					SendMessage(T_CUSTOMER, groups[customers[i].groupNumber][j-1], YouAreInSeat, index);
					/*printf("%s is putting %s in seat %d-%d\n",myName,((Customer *)subs->Get(j -1))->myName,*r,*c);*/
					seating[startingSeat+j] = groups[customers[i].groupNumber][j-1];
				}
				_seated=1;
				break;
			}
		}
	}
	
	/*If there weren't any adjacent rows with enough seats for the group, just find the first they can*/
	if(!_seated)
	{
		/*printf("no adjacent rows\n\n");*/
		seatsAssigned = 0;
		for(i=0;i<NUM_ROWS;i++)
		{
			for(j=0;j<NUM_COLS;j++)
			{
				int cust= seating[i*NUM_COLS + j];
				if((cust > -1) && seatsAssigned < (customers[index].numSubs + 1))
				{
					if(!seatsAssigned) /*seat lead*/
					{
						seating[i*NUM_COLS + j] = index;
						customers[index].myRow = i;
						customers[index].myCol = j;
						seatsAssigned = seatsAssigned + 1;
					}
					else
					{
						r = i;
						c = j;
						/*((Customer *)subs->Get(seatsAssigned-1))->SendMessage("YouAreInSeat",3,this,r,c);*/
						/*printf("%s is putting %s in seat %d-%d\n",myName,((Customer *)subs->Get(seatsAssigned-1))->myName,*r,*c);*/
						/*cinema->theater->seating[i*NUM_COLS + j] = ((Customer *)subs->Get(seatsAssigned-1));*/
						seatAssign[groups[customers[i].groupNumber][seatsAssigned-1]].row = r;
						seatAssign[groups[customers[i].groupNumber][seatsAssigned-1]].col = c;
						SendMessage(T_CUSTOMER, groups[customers[i].groupNumber][seatsAssigned-1], YouAreInSeat, index);
						seating[i*NUM_COLS + j] = groups[customers[i].groupNumber][seatsAssigned-1];
						seatsAssigned = seatsAssigned + 1;
					}
				}
			}
			if(seatsAssigned == (customers[i].numSubs + 1)) break;
		}
		_seated = 1;
	}
	
	
	/**/
	if(!runSchedulers) /*print seating chart if running tests*/
	{
		/*printf("Customer %s with group size %d seated now, printing seating chart:\n", myName, numSubs+1);*/
		for(i=0;i<NUM_ROWS;i++)
		{
			for(j=0;j<NUM_COLS;j++)
			{
				if(seating[i*NUM_COLS+j] > -1)
				{
					/*printf("| G-%-2d |", ((Customer *)(getCineplex()->theater->seating[i*NUM_COLS+j]))->groupNumber);*/
				}
				else
				{
					/*printf("| ____ |");*/
				}
			}
			/*printf("\n");*/
		}
	}
	Release(loopLock);
	Release(seatingLock);
	/*printf("Customer %s in Group %d is sitting in seat %d-%d\n", myName, groupNumber, myRow, myCol);*/
	customers[index].state = WATCHINGMOVIE;
}

void Customer_WatchingMovie(int index)
{
 	Acquire(customers[index].msgLock);
	/*IterList* leaveMsg = msgList->Find("MovieIsDone");*/
	Customer_GetMessage(index, MovieIsDone);
	if(customers[index].tempMsg.sender > -1)
	{
		customers[index].repliesWaiting = customers[index].numSubs;
		/*printf("Customer %s in Group %d is leaving seat %d-%d\n", myName, groupNumber, myRow, myCol);*/
		customers[index].state = LEADREGROUP;
		Release(customers[index].msgLock);
	}else{
		Wait(customers[index].sleepCon, customers[index].msgLock);
	}
}

void Customer_LeadRegroup(int index)
{
	if(customers[index].repliesWaiting == 0)
	{
		Acquire(seatingLock);
		seating[customers[index].myRow*NUM_COLS + customers[index].myCol] = -1;
		seatsFilled = seatsFilled - 1;
		/*printf("Theater->SeatsFilled = %d\n",cinema->theater->seatsFilled);*/
		customers[index].myRow = -1;
		customers[index].myCol = -1;
		Release(seatingLock);
		customers[index].msgsToSend = customers[index].numSubs;
		customers[index].state = ASKUSEBR;
	}else{
		Acquire(customers[index].msgLock);
		/*IterList* brMsg = msgList->Find("HaveRegrouped");*/
		Customer_GetMessage(index, HaveRegrouped);
		if(customers[index].tempMsg.sender > -1)
		{
			customers[index].repliesWaiting = customers[index].repliesWaiting - 1;
			Release(customers[index].msgLock);
		}else{
			Wait(customers[index].sleepCon, customers[index].msgLock);
		}
	}
}

void Customer_AskUseBR(int index)
{
	if(customers[index].msgsToSend == 0)
	{
		customers[index].repliesWaiting = customers[index].numSubs;
		customers[index].state = FINDOUTBR;
	}else{
		/*((Customer*)subs->Get(msgsToSend-1))->SendMessage("DoYouNeedBR",1,this);*/
		SendMessage(T_CUSTOMER, groups[customers[index].groupNumber][customers[index].msgsToSend - 1], DoYouNeedBR, index);
		customers[index].msgsToSend = customers[index].msgsToSend - 1;
	}
}

void Customer_FindOutBR(int index)
{
	if(customers[index].repliesWaiting == 0)
	{
		customers[index].state = WAITBR;
	}else{
		Acquire(customers[index].msgLock);
		/*IterList* brMsg = msgList->Find("NeedBR");*/
		Customer_GetMessage(index, NeedBR);
		if(customers[index].tempMsg.sender > -1)
		{
			/*if(brMsg->GetInt(0)) brQueue->Append(brMsg->Get(0));*/
			if(customers[customers[index].tempMsg.sender].subsInBR) customers[index].subsInBR = customers[index].subsInBR + 1;
			customers[index].repliesWaiting = customers[index].repliesWaiting - 1;
			Release(customers[index].msgLock);
		}else{
			Wait(customers[index].sleepCon, customers[index].msgLock);
		}
	}
}

void Customer_WaitBR(int index)
{
	if(customers[index].subsInBR == 0)
	{
		customers[index].msgsToSend = customers[index].numSubs;
		customers[index].state = LEAVECINEPLEX;
	}
	else
	{
		Acquire(customers[index].msgLock);
		/*IterList* brMsg = msgList->Find("BackFromBR");*/
		Customer_GetMessage(index, BackFromBR);
		if(customers[index].tempMsg.sender > -1)
		{
			customers[index].subsInBR = customers[index].subsInBR - 1;
			Release(customers[index].msgLock);
		}else{
			Wait(customers[index].sleepCon, customers[index].msgLock);
		}
	}
}

void Customer_LeaveCineplex(int index)
{
	if(customers[index].msgsToSend == 0)
	{
		/*printf("Customer %s in Group %d has left the movie theater\n", myName, groupNumber);*/
		customers[index].state = COMPLETED;
	}else{
		/*((Customer*)subs->Get(msgsToSend-1))->SendMessage("LeaveCineplex",0);*/
		SendMessage(T_CUSTOMER, groups[customers[index].groupNumber][customers[index].msgsToSend-1], LeaveCineplex, index);
		customers[index].msgsToSend = customers[index].msgsToSend - 1;
	}
}

void Customer_GoToLobby(int index)
{
	/*((Lobby*)replyTo)->SendMessage("IAmInLobby", 1, this);*/
	SendMessage(T_LOBBY, 0, IAmInLobby, index);
	/*printf("Customer %s has lead Group %d to the Lobby\n", myName, groupNumber);*/
	customers[index].state = INLOBBY;
}

void Customer_InLobby(int index)
{
	Acquire(customers[index].msgLock);
	/*IterList* lobbyMsg = msgList->Find("HowManyInYourGroup");*/
	Customer_GetMessage(index, HowManyInYourGroup);
	if(customers[index].tempMsg.sender > -1)
	{
		customers[index].state = RECSIZEREQUEST;
		Release(customers[index].msgLock);
	}else{
		/*IterList* enterMsg = msgList->Find("LeaveLobby");*/
		Customer_GetMessage(index, LeaveLobby);
		if(customers[index].tempMsg.sender > -1)
		{
			/*printf("Customer %s is leading Group %d out of the Lobby\n", myName, groupNumber);*/
			customers[index].state = JOINENTRYLINE;
			Release(customers[index].msgLock);
		}else{
			Wait(customers[index].sleepCon, customers[index].msgLock);
		}
	}
}

void Customer_RecSizeRequest(int index)
{
	/*((Lobby*)replyTo)->SendMessage("WeAreLegion", 2, this, &msgInt);*/
	SendMessage(T_LOBBY, 0, WeAreLegion, index);
	customers[index].state = INLOBBY;
}
/*SUB ACTIONS*/
void Customer_sNewSub(int index)
{
	Acquire(customers[index].msgLock);
	/*IterList* foodMsg = msgList->Find("WouldYouLikeFood");*/
	Customer_GetMessage(index, WouldYouLikeFood);
	if(customers[index].tempMsg.sender > -1)
	{
		customers[index].replyTo = customers[index].tempMsg.sender;
		customers[index].state = SSENDFOODORDER;
		Release(customers[index].msgLock);
	}else{
		Wait(customers[index].sleepCon, customers[index].msgLock);
	}
}

void Customer_sSendFoodOrder(int index)
{
	customers[index].numPopcorn = ((getRandPercent() < 75) ? 1 : 0); /*decide own popcorn*/
	customers[index].numSoda = ((getRandPercent() < 75) ? 1 : 0); /*decide own soda*/
	/*((Customer*)replyTo)->SendMessage("IWouldLike",2,&numPopcorn,&numSoda);*/
	SendMessage(T_CUSTOMER, customers[index].replyTo, IWouldLike, index);
	/*printf("Customer %s in group %d wants %d popcorn and %d soda.\n", myName, groupNumber, numPopcorn, numSoda);*/
	customers[index].state = SFOODORDERSENT;
}

void Customer_sFoodOrderSent(int index)
{
	Acquire(customers[index].msgLock);
	/*IterList* enterMsg = msgList->Find("GoOnIn");*/
	Customer_GetMessage(index, GoOnIn);
	if(customers[index].tempMsg.sender > -1)
	{
		customers[index].replyTo = customers[customers[index].tempMsg.sender].currentLine; /*problem solved B|*/
		customers[index].state = SRECGOIN;
		Release(customers[index].msgLock);
	}else{
		Wait(customers[index].sleepCon, customers[index].msgLock);
	}
}

void Customer_sRecGoIn(int index)
{
	/*((TicketTaker*)replyTo)->SendMessage("ImGoingIn",0);*/
	/*printf("Customer %s going in to sit\n",myName);*/
	SendMessage(T_TICKETTAKER, customers[index].replyTo, ImGoingIn, index);
	customers[index].state = SWAITFORSEAT;
}

void Customer_sWaitForSeat(int index)
{
	Acquire(customers[index].msgLock);
	/*IterList* seatMsg = msgList->Find("YouAreInSeat");*/
	Customer_GetMessage(index, YouAreInSeat);
	if(customers[index].tempMsg.sender > -1)
	{
		customers[index].replyTo = customers[index].tempMsg.sender;
		customers[index].myRow = seatAssign[index].row;
		customers[index].myCol = seatAssign[index].col;
		/*printf("Sub Customer %s in Group %d is sitting in seat %d-%d\n", myName, groupNumber, myRow, myCol);*/
		customers[index].state = SWATCHINGMOVIE;
		Release(customers[index].msgLock);
	}else{
		Wait(customers[index].sleepCon, customers[index].msgLock);
	}
}

void Customer_sWatchingMovie(int index)
{
	Acquire(customers[index].msgLock);
	/*IterList* seatMsg = msgList->Find("MovieIsDone");*/
	Customer_GetMessage(index, MovieIsDone);
	if(customers[index].tempMsg.sender > -1)
	{
		/*printf("Sub Customer %s in Group %d is leaving seat %d-%d\n", myName, groupNumber, myRow, myCol);*/
		customers[index].state = SREGROUP;
		Release(customers[index].msgLock);
	}else{
		Wait(customers[index].sleepCon, customers[index].msgLock);
	}
}

void Customer_sRegroup(int index)
{
	Acquire(seatingLock);
	seating[customers[index].myRow*NUM_COLS + customers[index].myCol] = -1;
	seatsFilled = seatsFilled - 1;
	customers[index].myRow = -1;
	customers[index].myCol = -1;
	/*printf("Theater->SeatsFilled = %d\n",cinema->theater->seatsFilled);*/
	Release(seatingLock);
	/*printf("Sub Customer %s in Group %d is regrouping\n", myName, groupNumber);*/
	/*((Customer*)replyTo)->SendMessage("HaveRegrouped",0);*/
	
	customers[index].state = SLEAVETHEATER;
}

void Customer_sLeaveTheater(int index)
{
	Acquire(customers[index].msgLock);
	/*IterList* brMsg = msgList->Find("DoYouNeedBR");*/
	Customer_GetMessage(index, DoYouNeedBR);
	if(customers[index].tempMsg.sender > -1)
	{
		customers[index].state = SASKEDBR;
		Release(customers[index].msgLock);
	}else{
		Wait(customers[index].sleepCon, customers[index].msgLock);
	}
}

void Customer_sAskedBR(index)
{
	if(getRandPercent() < 25)
	{
		customers[index].subsInBR = 1;
		/*((Customer*)replyTo)->SendMessage("NeedBR",1,&msgInt); //NEED*/
		SendMessage(T_CUSTOMER, customers[index].replyTo, NeedBR, index);
		customers[index].state = SUSEBR;
	}else{
		customers[index].subsInBR = 0;
		/*((Customer*)replyTo)->SendMessage("NeedBR",1,&msgInt); //DON'T NEED*/
		SendMessage(T_CUSTOMER, customers[index].replyTo, NeedBR, index);
		customers[index].state = SWAITBR;
	}
}

void Customer_sUseBR(int index)
{
	Acquire(brLock);
	/*printf("Customer %s in Group %d is using the bathroom\n", myName, groupNumber);*/
	for(brLock = 0; i < getRandPercent(); i++)
	{
		Yield();
	}
	Release(brLock);
	/*printf("Customer %s in Group %d is leaving the bathroom\n", myName, groupNumber);*/
	/*((Customer*)replyTo)->SendMessage("BackFromBR",0);*/
	SendMessage(T_CUSTOMER, customers[index].replyTo, BackFromBR, index);
	customers[index].state = SWAITBR;
}

void Customer_sWaitBR(int index)
{
	Acquire(customers[index].msgLock);
	/*IterList* leaveMsg = msgList->Find("LeaveCineplex");*/
	Customer_GetMessage(index, LeaveCineplex);
	if(customers[index].tempMsg.sender > -1)
	{
		customers[index].state = SLEAVECINEPLEX;
		Release(customers[index].msgLock);
	}else{
		Wait(customers[index].sleepCon, customers[index].msgLock);
	}
}

void Customer_sLeaveCineplex(int index)
{
	/*printf("Customer %s in Group %d has left the movie theater\n", myName, groupNumber);*/
	customers[index].state = COMPLETED;
}
